Micron Document
<!DOCTYPE html>
<html class="client-nojs vector-feature-night-mode-disabled vector-feature-language-in-header-enabled vector-feature-language-in-main-page-header-disabled vector-feature-page-tools-pinned-disabled vector-feature-toc-pinned-clientpref-1 vector-feature-main-menu-pinned-disabled vector-feature-limited-width-clientpref-1 vector-feature-limited-width-content-enabled vector-feature-custom-font-size-clientpref-1 vector-feature-appearance-pinned-clientpref-1 vector-sticky-header-enabled" lang="en" dir="ltr"><head>
<meta charset="UTF-8">
<title>Defunctionalization</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="canonical" href="https://en.wikipedia.org/wiki/Defunctionalization"> <link href="./mw/ext.pygments.css" rel="stylesheet" type="text/css">
<link href="./mw/skins.vector.icons.css" rel="stylesheet" type="text/css">
<link href="./mw/skins.vector.search.codex.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/skins.vector.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/user.styles.css" rel="stylesheet" type="text/css">
<meta name="ResourceLoaderDynamicStyles" content="">
<link rel="stylesheet" type="text/css" href="./mw/site.styles.css">
<link rel="stylesheet" type="text/css" href="./mw/noscript.css">
<link rel="stylesheet" type="text/css" href="./footer.css">
<link rel="stylesheet" type="text/css" href="./vector-2022.css">
</head>
<body class="skin--responsive skin-vector skin-vector-search-vue mediawiki ltr sitedir-ltr mw-hide-empty-elt ns-0 ns-subject page-Defunctionalization rootpage-Defunctionalization skin-vector-2022 action-view">
<div class="mw-page-container">
<div class="mw-page-container-inner">
<div class="mw-content-container">
<main id="content" class="mw-body">
<header class="mw-body-header vector-page-titlebar">
<h1 id="firstHeading" class="firstHeading mw-first-heading">
<span id="openzim-page-title" class="mw-page-title-main"><span class="mw-page-title-main">Defunctionalization</span></span>
</h1>
</header>
<a id="top"></a>
<div id="bodyContent" class="vector-body ve-init-mw-desktopArticleTarget-targetContainer" aria-labelledby="firstHeading" data-mw-ve-target-container="">
<div id="mw-content-text" class="mw-body-content mw-content-ltr" lang="en" dir="ltr"><div class="mw-content-ltr mw-parser-output" lang="en" dir="ltr">
<p>In <a href="Programming_languages" class="mw-redirect" title="Programming languages">programming languages</a>, <b>defunctionalization</b> is a <a href="Compile_time" title="Compile time">compile-time</a> transformation which eliminates <a href="Higher-order_function" title="Higher-order function">higher-order functions</a>, replacing them by a single first-order <i>apply</i> function. The technique was first described by <a href="John_C._Reynolds" title="John C. Reynolds">John C. Reynolds</a> in his 1972 paper, "Definitional Interpreters for Higher-Order Programming Languages". Reynolds' observation was that a given program contains only finitely many function abstractions, so that each can be assigned and replaced by a unique identifier. Every function application within the program is then replaced by a call to the <i>apply</i> function with the function identifier as the first argument. The <i>apply</i> function's only job is to dispatch on this first argument, and then perform the instructions denoted by the function identifier on the remaining arguments.
</p><p>One complication to this basic idea is that <a href="Abstraction_(computer_science)" title="Abstraction (computer science)">function abstractions</a> may reference <a href="Free_variables" class="mw-redirect" title="Free variables">free variables</a>. In such situations, defunctionalization must be preceded by <a href="Closure_conversion" class="mw-redirect" title="Closure conversion">closure conversion (lambda lifting)</a>, so that any free variables of a function abstraction are passed as extra arguments to <i>apply</i>. In addition, if <a href="Closure_(computer_science)" class="mw-redirect" title="Closure (computer science)">closures</a> are supported as <a href="First-class_value" class="mw-redirect" title="First-class value">first-class values</a>, it becomes necessary to represent these captured bindings by creating data structures.
</p><p>Instead of having a single <i>apply</i> function dispatch on all function abstractions in a program, various kinds of <a href="Control_flow_analysis" class="mw-redirect" title="Control flow analysis">control flow analysis</a> (including simple distinctions based on <a href="Arity" title="Arity">arity</a> or <a href="Type_signature" title="Type signature">type signature</a>) can be employed to determine which function(s) may be called at each function application site, and a specialized <i>apply</i> function may be referenced instead. Alternatively, the target language may support indirect calls through <a href="Function_pointer" title="Function pointer">function pointers</a>, which may be more efficient and extensible than a dispatch-based approach.
</p><p>Besides its use as a compilation technique for higher-order <a href="Functional_languages" class="mw-redirect" title="Functional languages">functional languages</a>, defunctionalization has been studied (particularly by <a href="Olivier_Danvy" title="Olivier Danvy">Olivier Danvy</a> and collaborators) as a way of mechanically transforming <a href="Interpreter_(computing)" title="Interpreter (computing)">interpreters</a> into <a href="Abstract_machine" title="Abstract machine">abstract machines</a>. Defunctionalization is also related to the technique from <a href="Object-oriented_programming" title="Object-oriented programming">object-oriented programming</a> of representing functions by <a href="Function_object" title="Function object">function objects</a> (as an alternative to closures).
</p>
<meta property="mw:PageProp/toc">
<div class="mw-heading mw-heading2"><h2 id="Example">Example</h2></div>
<p>This is an example given by <a href="Olivier_Danvy" title="Olivier Danvy">Olivier Danvy</a>, translated to Haskell:
</p><p>Given the Tree datatype:
</p>
<div class="mw-highlight mw-highlight-lang-haskell mw-content-ltr" dir="ltr"><pre><span class="kr">data</span><span class="w"> </span><span class="kt">Tree</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Leaf</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Node</span><span class="w"> </span><span class="p">(</span><span class="kt">Tree</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">Tree</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
</pre></div>
<p>We will defunctionalize the following program:
</p>
<div class="mw-highlight mw-highlight-lang-haskell mw-content-ltr" dir="ltr"><pre><span class="nf">cons</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span>
<span class="nf">cons</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="kt">:</span><span class="w"> </span><span class="n">xs</span>

<span class="nf">o</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="n">b</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="n">c</span><span class="p">)</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="n">c</span>
<span class="nf">o</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">(</span><span class="n">g</span><span class="w"> </span><span class="n">x</span><span class="p">)</span>

<span class="nf">flatten</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Tree</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="p">[</span><span class="n">t</span><span class="p">]</span>
<span class="nf">flatten</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">walk</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="kt">[]</span>

<span class="nf">walk</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Tree</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="p">[</span><span class="n">t</span><span class="p">]</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="p">[</span><span class="n">t</span><span class="p">]</span>
<span class="nf">walk</span><span class="w"> </span><span class="p">(</span><span class="kt">Leaf</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">cons</span><span class="w"> </span><span class="n">x</span>
<span class="nf">walk</span><span class="w"> </span><span class="p">(</span><span class="kt">Node</span><span class="w"> </span><span class="n">t1</span><span class="w"> </span><span class="n">t2</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">o</span><span class="w"> </span><span class="p">(</span><span class="n">walk</span><span class="w"> </span><span class="n">t1</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="n">walk</span><span class="w"> </span><span class="n">t2</span><span class="p">)</span>
</pre></div>
<p>We defunctionalize by replacing all higher-order functions (in this case, <code>o</code> is the only higher-order function) with a value of the <code>Lam</code> datatype, and instead of calling them directly, we introduce an <code>apply</code> function that interprets the datatype:
</p>
<div class="mw-highlight mw-highlight-lang-haskell mw-content-ltr" dir="ltr"><pre><span class="kr">data</span><span class="w"> </span><span class="kt">Lam</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">LamCons</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">LamO</span><span class="w"> </span><span class="p">(</span><span class="kt">Lam</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">Lam</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>

<span class="nf">apply</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Lam</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span>
<span class="nf">apply</span><span class="w"> </span><span class="p">(</span><span class="kt">LamCons</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="kt">:</span><span class="w"> </span><span class="n">xs</span>
<span class="nf">apply</span><span class="w"> </span><span class="p">(</span><span class="kt">LamO</span><span class="w"> </span><span class="n">f1</span><span class="w"> </span><span class="n">f2</span><span class="p">)</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">apply</span><span class="w"> </span><span class="n">f1</span><span class="w"> </span><span class="p">(</span><span class="n">apply</span><span class="w"> </span><span class="n">f2</span><span class="w"> </span><span class="n">xs</span><span class="p">)</span>

<span class="nf">cons_def</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Lam</span><span class="w"> </span><span class="n">a</span>
<span class="nf">cons_def</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">LamCons</span><span class="w"> </span><span class="n">x</span>

<span class="nf">o_def</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Lam</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Lam</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Lam</span><span class="w"> </span><span class="n">a</span>
<span class="nf">o_def</span><span class="w"> </span><span class="n">f1</span><span class="w"> </span><span class="n">f2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">LamO</span><span class="w"> </span><span class="n">f1</span><span class="w"> </span><span class="n">f2</span>

<span class="nf">flatten_def</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Tree</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="p">[</span><span class="n">t</span><span class="p">]</span>
<span class="nf">flatten_def</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">apply</span><span class="w"> </span><span class="p">(</span><span class="n">walk_def</span><span class="w"> </span><span class="n">t</span><span class="p">)</span><span class="w"> </span><span class="kt">[]</span>

<span class="nf">walk_def</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Tree</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Lam</span><span class="w"> </span><span class="n">t</span>
<span class="nf">walk_def</span><span class="w"> </span><span class="p">(</span><span class="kt">Leaf</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">cons_def</span><span class="w"> </span><span class="n">x</span>
<span class="nf">walk_def</span><span class="w"> </span><span class="p">(</span><span class="kt">Node</span><span class="w"> </span><span class="n">t1</span><span class="w"> </span><span class="n">t2</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">o_def</span><span class="w"> </span><span class="p">(</span><span class="n">walk_def</span><span class="w"> </span><span class="n">t1</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="n">walk_def</span><span class="w"> </span><span class="n">t2</span><span class="p">)</span>
</pre></div>
<div class="mw-heading mw-heading2"><h2 id="See_also">See also</h2></div>
<ul><li><a href="Closure_conversion" class="mw-redirect" title="Closure conversion">Closure conversion</a></li>
<li><a href="Partial_evaluation" title="Partial evaluation">Partial evaluation</a></li></ul>
<div class="mw-heading mw-heading2"><h2 id="References">References</h2></div>
<ul><li><style data-mw-deduplicate="TemplateStyles:r1238218222">
/* start https://en.wikipedia.org/ */


.mw-parser-output cite.citation{font-style:inherit;word-wrap:break-word}.mw-parser-output .citation q{quotes:"\"""\"""'""'"}.mw-parser-output .citation:target{background-color:rgba(0,127,255,0.133)}.mw-parser-output .id-lock-free.id-lock-free a{background:url("./mw/Lock-green.svg")right 0.1em center/9px no-repeat}.mw-parser-output .id-lock-limited.id-lock-limited a,.mw-parser-output .id-lock-registration.id-lock-registration a{background:url("./mw/Lock-gray-alt-2.svg")right 0.1em center/9px no-repeat}.mw-parser-output .id-lock-subscription.id-lock-subscription a{background:url("./mw/Lock-red-alt-2.svg")right 0.1em center/9px no-repeat}.mw-parser-output .cs1-ws-icon a{background:url("./mw/Wikisource-logo.svg")right 0.1em center/12px no-repeat}body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-free a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-limited a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-registration a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-subscription a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .cs1-ws-icon a{background-size:contain;padding:0 1em 0 0}.mw-parser-output .cs1-code{color:inherit;background:inherit;border:none;padding:inherit}.mw-parser-output .cs1-hidden-error{display:none;color:var(--color-error,#d33)}.mw-parser-output .cs1-visible-error{color:var(--color-error,#d33)}.mw-parser-output .cs1-maint{display:none;color:#085;margin-left:0.3em}.mw-parser-output .cs1-kern-left{padding-left:0.2em}.mw-parser-output .cs1-kern-right{padding-right:0.2em}.mw-parser-output .citation .mw-selflink{font-weight:inherit}@media screen{.mw-parser-output .cs1-format{font-size:95%}html.skin-theme-clientpref-night .mw-parser-output .cs1-maint{color:#18911f}}@media screen and (prefers-color-scheme:dark){html.skin-theme-clientpref-os .mw-parser-output .cs1-maint{color:#18911f}}


/* end https://en.wikipedia.org/ */
</style><cite id="CITEREFReynolds1972" class="citation conference cs1"><a href="John_C._Reynolds" title="John C. Reynolds">Reynolds, John</a> (August 1972). "Definitional Interpreters for Higher-Order Programming Languages". <i>Proceedings of the ACM Annual Conference</i>. Boston, Massachusetts. pp.&nbsp;<span class="nowrap">717–</span>740. <a href="Doi_(identifier)" class="mw-redirect" title="Doi (identifier)">doi</a>:<a rel="nofollow" class="external text" href="https://doi.org/10.1145%2F800194.805852">10.1145/800194.805852</a>.</cite></li>
<li><cite id="CITEREFDanvyNielsen2001" class="citation conference cs1"><a href="Olivier_Danvy" title="Olivier Danvy">Danvy, Olivier</a>; Nielsen, Lasse R. (2001). <a rel="nofollow" class="external text" href="http://www.daimi.au.dk/~danvy/DSc/22_danvy-nielsen_ppdp-2001.pdf">"Defunctionalization at Work"</a> <span class="cs1-format">(PDF)</span>. <i>Proceedings of the ACM SIGPLAN Conference on Principles and Practice of Declarative Programming</i>. pp.&nbsp;<span class="nowrap">162–</span>174. <a href="Doi_(identifier)" class="mw-redirect" title="Doi (identifier)">doi</a>:<a rel="nofollow" class="external text" href="https://doi.org/10.1145%2F773184.773202">10.1145/773184.773202</a>.</cite> (More comprehensive version: <a rel="nofollow" class="external text" href="http://www.brics.dk/RS/01/23/BRICS-RS-01-23.pdf">Technical Report BRICS-RS-01-23</a>)</li>
<li><cite id="CITEREFDanvyMillikin2009" class="citation journal cs1"><a href="Olivier_Danvy" title="Olivier Danvy">Danvy, Olivier</a>; Millikin, Kevin R. (June 2009). "Refunctionalization at Work". <i>Science of Computer Programming</i>. <b>74</b> (8): <span class="nowrap">534–</span>549. <a href="Doi_(identifier)" class="mw-redirect" title="Doi (identifier)">doi</a>:<a rel="nofollow" class="external text" href="https://doi.org/10.1016%2Fj.scico.2007.10.007">10.1016/j.scico.2007.10.007</a>.</cite> (Also available as <a rel="nofollow" class="external text" href="http://www.brics.dk/RS/07/7/BRICS-RS-07-7.pdf">Technical Report BRICS-RS-07-7</a>)</li></ul>
<div class="mw-heading mw-heading2"><h2 id="External_links">External links</h2></div>
<ul><li><a rel="nofollow" class="external text" href="https://spivey.oriel.ox.ac.uk/corner/Defunctionalization_(Programming_Languages)">Defunctionalization (Programming Languages)</a>. Oxford University.</li></ul></div><!--htdig_noindex--><div><div class="zim-footer">
This article is issued from <a class="external text" title="Last edited on 2024-04-06" href="https://en.wikipedia.org/wiki/?title=Defunctionalization&amp;oldid=1217506827">Wikipedia</a>. The text is available under <a class="external text" href="https://creativecommons.org/licenses/by-sa/4.0/deed.en">Creative Commons Attribution-Share Alike 4.0</a> unless otherwise noted. Additional terms may apply for the media files.
</div>
</div><!--/htdig_noindex--></div>
</div>
</main>
</div>
</div>
</div>

</body></html>